package com.apes.framework.plugin.soe.metadata;

import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.BaseModel;
import com.apes.framework.jpa.DefaultPersistListener;
import com.apes.framework.jpa.Name;
import com.apes.framework.jpa.generator.ApesGenerator;
import com.apes.framework.jpa.generator.service.SequenceService;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.SelectBeforeUpdate;
import org.springframework.util.StringUtils;

import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;

/**
 * 功能：凭证属性
 *
 * @author xul
 * @create 2018-09-27 15:51
 */
@Getter
@Setter
@SelectBeforeUpdate
@DynamicInsert
@DynamicUpdate
@Entity
@EntityListeners(DefaultPersistListener.class)
@Table(name = BusinessAttribute.CONST_TABLE_NAME, indexes = {
        @Index(name = "u_soe_business_attr", columnList = "business_type_Id, code", unique = true)})
public class BusinessAttribute extends BaseModel {
    public static final String CONST_TABLE_NAME = "soe_business_attr";

    @Id
    @Column(name = "id", length = 120)
    //@ApesGenerator(code = CONST_TABLE_NAME, name = "凭证属性")
    private String id;   //编码

    public void setId() {
        StringBuffer sb = new StringBuffer();
        sb.append(businessType.getId()).append(".").append(code);
        this.id =  sb.toString();
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "business_type_id", nullable = false, referencedColumnName = "id")
    private BusinessType businessType; //凭证类型（目标）

    @Name
    @Column(name = "code", nullable = false, length = 120)
    private String code; //属性

    @Column(name = "name", nullable = false, length = 120)
    private String name; //名称

    @Column(name = "valid", columnDefinition = "number(1,0) default 1")
    private boolean valid = true; //是否有效

    @OneToMany(mappedBy = "businessAttribute", cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<BusinessAttributeValue> businessAttributeValues = new HashSet<>(); // 属性值

    public Set<BusinessAttributeValue> getBusinessAttributeValues() {
        for (BusinessAttributeValue businessAttributeValue : businessAttributeValues) {
            businessAttributeValue.setBusinessAttribute(this);
        }
        return businessAttributeValues;
    }

    public boolean merge(BusinessAttribute other) {
        boolean changed = false;
        if (this.equals(other)) return changed;
        if (!getCode().equals(other.getCode())) setCode(other.getCode());
        if (!getName().equals(other.getName())) setName(other.getName());

        for (BusinessAttributeValue obav : businessAttributeValues) {
            if (obav.isValid() && other.getBusinessAttributeValues().stream().filter(nbav -> nbav.getCode().equals(obav.getCode())).count() == 0) {
                obav.setValid(false);
                changed = true;
            }
        }

        for (BusinessAttributeValue nbav : other.getBusinessAttributeValues()) {
            boolean exist = false;
            for (BusinessAttributeValue attributeValue : businessAttributeValues) {
                if (!attributeValue.getCode().equals(nbav.getCode())) continue;
                if (attributeValue.merge(nbav)) changed = true;
                exist = true;
            }
            if (!exist) {
                nbav.setBusinessAttribute(this);
                businessAttributeValues.add(nbav);
                changed = true;
            }
        }
        return changed;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof BusinessAttribute)) return false;
        BusinessAttribute that = (BusinessAttribute) o;
        //if (getId() != null ? getId().equals(that.getId()) : false) return true;
        if (!getCode().equals(that.getCode())) return false;
        if (!getName().equals(that.getName())) return false;

        if (getBusinessAttributeValues().size() != that.getBusinessAttributeValues().size()) return false;
        if (getBusinessAttributeValues().containsAll(that.getBusinessAttributeValues())) return true;
        for (BusinessAttributeValue bav : getBusinessAttributeValues()) {
            if (that.getBusinessAttributeValues().stream().filter(nbav -> nbav.equals(bav)).count() == 0) return false;
        }
        return true;
    }

}
